<script lang="ts" setup>
import type { CropendResult, CropperType } from '#/components/cropper/typing';

import { ref, watch } from 'vue';

import { useVbenModal } from '@vben/common-ui';
import { IconifyIcon } from '@vben/icons';
import { dataURLtoBlob, isFunction } from '@vben/utils';

import {
  Button,
  message,
  Radio,
  RadioGroup,
  Space,
  Tooltip,
  Upload,
} from 'ant-design-vue';

import CropperImage from '#/components/cropper/cropper.vue';

defineOptions({ name: 'DressCropperModal' });

interface Props {
  src?: string;
  uploadApi?: (params: { file: Blob; filename: string; name: string }) => Promise<any>;
  size?: number;
  filename?: string;
  editingFile?: any;
}

const props = withDefaults(defineProps<Props>(), {
  src: '',
  size: 5,
  filename: '',
});

const emit = defineEmits(['uploadSuccess', 'uploadError']);

let filename = props.filename || '';
const src = ref(props.src || '');
const previewSource = ref('');
const cropper = ref<CropperType>();
const aspectRatio = ref<number | undefined>(1);
const isFullscreen = ref(false);
let scaleX = 1;
let scaleY = 1;

// 监听 props.src 变化
watch(
  () => props.src,
  (newSrc) => {
    src.value = newSrc;
  },
);

// 预设比例选项
const aspectRatioOptions = [
  { label: '自由', value: undefined },
  { label: '1:1 (正方形)', value: 1 },
  { label: '4:3 (横向)', value: 4 / 3 },
  { label: '3:4 (竖向)', value: 3 / 4 },
  { label: '16:9 (宽屏)', value: 16 / 9 },
  { label: '9:16 (手机)', value: 9 / 16 },
];

const [Modal, modalApi] = useVbenModal({
  onConfirm: handleOk,
  onOpenChange(isOpen) {
    if (isOpen) {
      // 获取传入的数据
      const data = modalApi.getData<any>();
      if (data?.src) {
        src.value = data.src;
      }
      if (data?.filename) {
        filename = data.filename;
      }
      
      // 打开时，进行 loading 加载
      modalLoading(true);
      const img = new Image();
      img.src = src.value;
      img.addEventListener('load', () => {
        modalLoading(false);
      });
      img.addEventListener('error', () => {
        modalLoading(false);
        message.error('图片加载失败');
      });
    } else {
      // 关闭时，清空预览
      previewSource.value = '';
      aspectRatio.value = 1;
      modalLoading(false);
    }
  },
});

function modalLoading(loading: boolean) {
  modalApi.setState({ confirmLoading: loading, loading });
}

// 比例变化时，重新应用到裁剪器并自动调整图片大小
watch(aspectRatio, (newRatio) => {
  if (cropper.value) {
    (cropper.value as any).setAspectRatio(newRatio || NaN);
    
    // 自动调整图片大小以适应新的比例
    setTimeout(() => {
      const canvasData = (cropper.value as any).getCanvasData();
      const containerData = (cropper.value as any).getContainerData();
      
      if (canvasData && containerData) {
        const scaleX = containerData.width / canvasData.naturalWidth;
        const scaleY = containerData.height / canvasData.naturalHeight;
        const scale = Math.min(scaleX, scaleY) * 0.9; // 留一些边距
        
        if (scale > 0) {
          (cropper.value as any).zoomTo(scale);
        }
      }
    }, 100);
  }
});

// 阻止上传，用于读取文件
function handleBeforeUpload(file: File) {
  if (props.size > 0 && file.size > 1024 * 1024 * props.size) {
    message.error(`图片大小不能超过 ${props.size}MB`);
    return false;
  }
  const reader = new FileReader();
  reader.readAsDataURL(file);
  src.value = '';
  previewSource.value = '';
  reader.addEventListener('load', (e) => {
    src.value = (e.target?.result as string) ?? '';
    filename = file.name;
  });
  return false;
}

function handleCropend({ imgBase64 }: CropendResult) {
  previewSource.value = imgBase64;
}

function handleReady(cropperInstance: CropperType) {
  cropper.value = cropperInstance;
  // 设置初始比例
  (cropperInstance as any).setAspectRatio(aspectRatio.value || NaN);
  
  // 让图片铺满裁剪区域
  setTimeout(() => {
    // 先重置到初始状态
    (cropperInstance as any).reset();
    
    // 计算合适的缩放比例
    const canvasData = (cropperInstance as any).getCanvasData();
    const containerData = (cropperInstance as any).getContainerData();
    
    if (canvasData && containerData) {
      const scaleX = containerData.width / canvasData.naturalWidth;
      const scaleY = containerData.height / canvasData.naturalHeight;
      const scale = Math.min(scaleX, scaleY) * 0.9; // 留一些边距
      
      if (scale > 0) {
        (cropperInstance as any).zoomTo(scale);
      }
    }
  }, 200);
  
  // 画布加载完毕 关闭 loading
  modalLoading(false);
}

// 适应画布功能
function fitToCanvas() {
  if (cropper.value) {
    const canvasData = (cropper.value as any).getCanvasData();
    const containerData = (cropper.value as any).getContainerData();
    
    if (canvasData && containerData) {
      const scaleX = containerData.width / canvasData.naturalWidth;
      const scaleY = containerData.height / canvasData.naturalHeight;
      const scale = Math.min(scaleX, scaleY) * 0.9; // 留一些边距
      
      if (scale > 0) {
        (cropper.value as any).zoomTo(scale);
      }
    }
  }
}

function handlerToolbar(event: string, arg?: number) {
  if (event === 'scaleX') {
    scaleX = arg = scaleX === -1 ? 1 : -1;
  }
  if (event === 'scaleY') {
    scaleY = arg = scaleY === -1 ? 1 : -1;
  }
  (cropper?.value as any)?.[event]?.(arg);
}

async function handleOk() {
  const uploadApi = modalApi.getData<any>()?.uploadApi || props.uploadApi;
  
  if (uploadApi && isFunction(uploadApi)) {
    if (!previewSource.value) {
      message.warn('请先裁剪图片');
      return;
    }
    const blob = dataURLtoBlob(previewSource.value);
    try {
      modalLoading(true);
      const result = await uploadApi({ file: blob, filename, name: 'file' });
      emit('uploadSuccess', { data: result, source: previewSource.value });
      await modalApi.close();
    } catch (error) {
      console.error('上传失败:', error);
      emit('uploadError', error);
    } finally {
      modalLoading(false);
    }
  }
}
</script>

<template>
  <Modal
    v-bind="$attrs"
    confirm-text="确认裁剪"
    :fullscreen-button="true"
    title="编辑婚纱图片"
    :width="isFullscreen ? '100vw' : '90vw'"
    :class="isFullscreen ? 'max-w-none h-screen' : 'max-w-none'"
  >
    <div :class="isFullscreen ? 'flex h-[calc(100vh-120px)] gap-6' : 'flex h-[70vh] gap-6'">
      <!-- 左侧裁剪区域 -->
      <div class="flex-1 flex flex-col">
        <!-- 裁剪器容器 -->
        <div
          class="relative flex-1 bg-gradient-to-b from-neutral-50 to-neutral-200 rounded-lg overflow-hidden min-h-[500px]"
        >
          <CropperImage
            v-if="src"
            :circled="false"
            :src="src"
            height="550px"
            @cropend="handleCropend"
            @ready="handleReady"
          />
        </div>

        <!-- 工具栏 -->
        <div class="mt-3 flex items-center justify-between">
          <Upload
            :before-upload="handleBeforeUpload"
            :file-list="[]"
            accept="image/*"
          >
            <Tooltip title="重新选择图片" placement="bottom">
              <Button size="small" type="primary">
                <template #icon>
                  <IconifyIcon icon="lucide:upload" />
                </template>
                选择图片
              </Button>
            </Tooltip>
          </Upload>

          <Space size="small">
            <Tooltip title="全屏编辑" placement="bottom">
              <Button
                size="small"
                type="default"
                @click="isFullscreen = !isFullscreen"
              >
                <template #icon>
                  <IconifyIcon :icon="isFullscreen ? 'lucide:minimize' : 'lucide:maximize'" />
                </template>
              </Button>
            </Tooltip>
            <Tooltip title="适应画布" placement="bottom">
              <Button
                :disabled="!src"
                size="small"
                type="default"
                @click="fitToCanvas"
              >
                <template #icon>
                  <IconifyIcon icon="lucide:fit-screen" />
                </template>
              </Button>
            </Tooltip>
            <Tooltip title="重置" placement="bottom">
              <Button
                :disabled="!src"
                size="small"
                type="default"
                @click="handlerToolbar('reset')"
              >
                <template #icon>
                  <IconifyIcon icon="lucide:rotate-ccw" />
                </template>
              </Button>
            </Tooltip>
            <Tooltip title="左旋转" placement="bottom">
              <Button
                :disabled="!src"
                size="small"
                type="default"
                @click="handlerToolbar('rotate', -45)"
              >
                <template #icon>
                  <IconifyIcon icon="ant-design:rotate-left-outlined" />
                </template>
              </Button>
            </Tooltip>
            <Tooltip title="右旋转" placement="bottom">
              <Button
                :disabled="!src"
                size="small"
                type="default"
                @click="handlerToolbar('rotate', 45)"
              >
                <template #icon>
                  <IconifyIcon icon="ant-design:rotate-right-outlined" />
                </template>
              </Button>
            </Tooltip>
            <Tooltip title="水平翻转" placement="bottom">
              <Button
                :disabled="!src"
                size="small"
                type="default"
                @click="handlerToolbar('scaleX')"
              >
                <template #icon>
                  <IconifyIcon icon="vaadin:arrows-long-h" />
                </template>
              </Button>
            </Tooltip>
            <Tooltip title="垂直翻转" placement="bottom">
              <Button
                :disabled="!src"
                size="small"
                type="default"
                @click="handlerToolbar('scaleY')"
              >
                <template #icon>
                  <IconifyIcon icon="vaadin:arrows-long-v" />
                </template>
              </Button>
            </Tooltip>
            <Tooltip title="放大" placement="bottom">
              <Button
                :disabled="!src"
                size="small"
                type="default"
                @click="handlerToolbar('zoom', 0.1)"
              >
                <template #icon>
                  <IconifyIcon icon="lucide:zoom-in" />
                </template>
              </Button>
            </Tooltip>
            <Tooltip title="缩小" placement="bottom">
              <Button
                :disabled="!src"
                size="small"
                type="default"
                @click="handlerToolbar('zoom', -0.1)"
              >
                <template #icon>
                  <IconifyIcon icon="lucide:zoom-out" />
                </template>
              </Button>
            </Tooltip>
          </Space>
        </div>
      </div>

      <!-- 右侧预览区域 -->
      <div class="w-96 flex flex-col">
        <div class="mb-3">
          <div class="text-sm font-medium mb-2">裁剪比例</div>
          <RadioGroup v-model:value="aspectRatio" button-style="solid" size="small">
            <Radio
              v-for="option in aspectRatioOptions"
              :key="option.label"
              :value="option.value"
              class="mb-2"
            >
              {{ option.label }}
            </Radio>
          </RadioGroup>
        </div>

        <div class="flex-1 flex flex-col">
          <div class="text-sm font-medium mb-2">预览效果</div>
          <div
            class="flex-1 border-2 border-dashed border-gray-300 rounded-lg overflow-hidden bg-gray-50 flex items-center justify-center min-h-[300px]"
          >
            <img
              v-if="previewSource"
              :src="previewSource"
              alt="预览"
              class="max-w-full max-h-full object-contain"
            />
            <div v-else class="text-gray-400 text-sm">
              <IconifyIcon icon="lucide:image" class="text-4xl mb-2" />
              <div>裁剪后预览</div>
            </div>
          </div>
        </div>

        <div class="mt-3 p-2 bg-blue-50 rounded-lg text-xs text-blue-600">
          <div class="flex items-start gap-2">
            <IconifyIcon icon="lucide:info" class="mt-0.5 flex-shrink-0" />
            <div>
              <div class="font-medium mb-1">使用技巧：</div>
              <ul class="list-disc list-inside space-y-1">
                <li>拖动图片调整位置</li>
                <li>滚轮缩放图片大小</li>
                <li>选择合适的裁剪比例</li>
                <li>点击"适应画布"按钮让图片铺满编辑区域</li>
                <li>建议使用 4:3 或 1:1 比例</li>
              </ul>
            </div>
          </div>
        </div>
      </div>
    </div>
  </Modal>
</template>

<style scoped>
:deep(.ant-radio-button-wrapper) {
  @apply text-xs px-2;
}
</style>

